package com.yumeng.config.properties;

import com.yumeng.common.data.enums2.AuthFrame;
import com.yumeng.common.exception.YumengException;
import com.yumeng.config.data.JwtConstants;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author wxd
 * @date 2024/5/29 上午9:49
 */
@Slf4j
@Getter
@Setter
@Component(YumengAuthProperties.DEFAULT_BEAN_NAME)
@ConfigurationProperties(prefix = "yumeng.auth")
public class YumengAuthProperties {

    public static final String DEFAULT_BEAN_NAME = "YumengAuthProperties";

    private YumengBasicProperties basic;
    private JwtProperties jwt;

    @Getter
    @Setter
    public static class YumengBasicProperties{

        //region security | shiro

        /** 当前认证框架 */
        @Getter
        private static AuthFrame currAuthFrame;
        public static void setCurrAuthFrame(AuthFrame currAuthFrame) {
            if (YumengBasicProperties.currAuthFrame != null) {//仅赋值一次
                throw new YumengException("当前认证框架标识已被赋值");
            }
            YumengBasicProperties.currAuthFrame = currAuthFrame;
        }
        /** 当前是否前后端分离 */
        @Getter
        private static Boolean isFBS = null;
        public static void setFBS(boolean isFBS){
            if (YumengBasicProperties.isFBS != null) {//仅赋值一次
                throw new YumengException("当前认证框架FBS标识已被赋值");
            }
            YumengBasicProperties.isFBS = isFBS;
        }


        /** 是否使用自定义登录Url */
        private boolean useLoginUrl = true;
        /** 登录url */
        private String loginUrl;
        public String getLoginUrl(){
            return useLoginUrl && StringUtils.isNotBlank(loginUrl) ? loginUrl : "/login";
        }
        /** 登录成功url */
        private String loginSuccessUrl;


        /** 用户名参数 */
        private String usernameParameter;
        /** 密码参数 */
        private String passwordParameter;
        /** 客户端类型参数 */
        private String clientTypeParameter;
        /** 记住我参数 */
        private String rememberMeParameter;

        //endregion

        //region shiro

        /** 未经授权的url */
        private String unauthorizedUrl;//security中，默认未认证的情况下，默认[LoginUrlAuthenticationEntryPoint]返回登录页

        //endregion

        //region security

        /** 登录接口 */
        private String loginAction;

        /** 注销url */
        private String logoutUrl;
        /** 注销接口 */
        private String logoutAction;
        /** 需要验证验证码的Url */
        private List<String> captchaVerifyUrls;
        /** 验证码参数 */
        private String captchaParameter;
        /** 验证码Id参数 */
        private String captchaIdParameter;
        /** sms登录url */
        private String smsLoginUrl;
        /** sms登录接口 */
        private String smsLoginAction;
        /** sms用户名参数 */
        private String smsUsernameParameter;
        /** sms密码参数 */
        private String smsPasswordParameter;
        /** csrf cookie 名称 */
        private String csrfCookieName;
        /** 需要放行的URL */
        private List<String> needPermitAllUrls;

        public String getLoginAction(){
            //基于默认FormAuthenticationFilter::onAccessDenied逻辑，登录处理url与登录页面url必须一致
            if (currAuthFrame.equals(AuthFrame.SHIRO)){
                return getLoginUrl();
            }else{
                return loginAction;
            }
        }

        //endregion
    }

    @Getter
    @Setter
    public static class JwtProperties {

        //=============================================================基础信息=============================================================
        /**
         * token名称,默认名称为：X-Token，可自定义
         */
        private String tokenName = JwtConstants.JWT_DEFAULT_HEADER_NAME;
        /**
         * refreshToken名称,默认名称为：X-Refresh-Token，可自定义
         */
        private String refreshTokenName = JwtConstants.JWT_REFRESH_TOKEN_DEFAULT_HEADER_NAME;

        /**
         * 密钥
         */
        private String secret = JwtConstants.JWT_DEFAULT_SECRET;
        /**
         * 签发人
         */
        private String issuer;
        /**
         * 主题
         */
        private String subject;
        /**
         * 签发的目标
         */
        private String audience;

        //=============================================================token失效时间=============================================================
        /**
         * （pc、mobile）token失效时间,默认2小时，2*60*60=7200
         */
        private Long expireSeconds = 7200L;
        /**
         * Remote端 token失效时间,默认24小时，24*60*60
         */
        private Long expireSecondsRemote = 86400L;
        //=============================================================失效倒计时=============================================================
        /**
         * （pc、mobile）刷新token倒计时，默认10分钟，10*60=600
         */
        private Integer refreshCountdown = 600;
        /**
         * Remote端 刷新token倒计时，默认60分钟，60*60
         */
        private Integer refreshCountdownRemote = 3600;
        //=============================================================刷新token失效时间=============================================================
        /**
         * pc端 refresh_token 有效期1天 24*3600
         */
        private Integer refreshTokenExpireSecondsPc = 86400;
        /**
         * mobile端 refresh_token 有效期7天
         */
        private Integer refreshTokenExpireSecondsMobile = 604800;
        //=============================================================其他=============================================================
        /**
         * 是否刷新token，默认为true
         */
        private Boolean refreshToken = true;
        /**
         * cache校验jwt token是否存在
         */
        private Boolean cacheCheck = true;

        /**
         * 单用户登录，一个用户只能有一个有效的token
         */
        private Boolean singleLogin = false;

        /**
         * 是否缓存jwt信息
         */
        private Boolean enableCache = true;

        /**
         * 最长登录时间 默认31天 24*3600*31
         */
        private Integer maxLoginSecond = 2678400;

    }

}
